﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using OS.Infrastructure.Domain;
using OS.Infrastructure.Domain.UnitOfWork;
using TaskKernel.Configuration;
using TaskKernel.DTO;
using TaskKernel.Domain;
using TaskKernel.Domain.Interface;
using TaskKernel.Domain.Services.Action;
using TaskKernel.Domain.Services.Mail;

namespace TaskWebApplicationUI.PresenterLayer
{
    public class ProposalPresenter : AbstractPresenter<IProposalFormView>
    {
        private readonly IQueryProposalForm _queryProposalForm;
        private readonly IMessageService _messageService;
        private readonly IUnitOfWorkFactory _uow;
        private readonly ICommandRepository<Task> _command;
        private readonly IQueryDepartment _queryDepartment;
        private readonly IQueryAccount _queryAccount;
        private readonly IQueryTask _queryTask;
        private ITaskAction _taskAction;
        private Account _currentAccount;
        private Department _currentDepartment;

        public ProposalPresenter(IQueryDepartment queryDepartment, IQueryAccount queryAccount, IQueryTask queryTask,
                                 IQueryProposalForm queryProposalForm, IMessageService messageService, ITaskAction taskAction,
            IUnitOfWorkFactory uow,ICommandRepository<Task> command)
        {
            _queryDepartment = queryDepartment;
            _queryAccount = queryAccount;
            _queryTask = queryTask;
            _taskAction = taskAction;
            _queryProposalForm = queryProposalForm;
            _messageService = messageService;
            _uow = uow;
            _command = command;
        }

        private Account CurrentAccount
        {
            get
            {
                if (_currentAccount != null)
                    return _currentAccount;
                if (!String.IsNullOrEmpty(View.LogonUser))
                {
                    _currentAccount = _queryAccount.Get(View.LogonUser);
                    if (_currentAccount != null)
                        return _currentAccount;
                }
                throw new NotImplementedException("Don't know who are you...");
            }
        }

        private Department CurrentDepartment
        {
            get
            {
                if (_currentDepartment != null)
                    return _currentDepartment;
                if (!String.IsNullOrEmpty(View.WebPath))
                {
                    _currentDepartment = _queryDepartment.GetDepartmentByWebPath(View.WebPath);
                    if (_currentDepartment != null) return _currentDepartment;
                    if (_queryDepartment == null)
                        throw new NotImplementedException("queryDepartment is null");
                }
                throw new NotImplementedException("Don't know where are you...");
            }
        }



        private void SetDepartmentName()
        {
            View.DepartmentName = CurrentDepartment.DepartmentName;
        }

        public virtual void OnViewInitialized()
        {
            using (var z = _uow.Create())
            {
                SetDepartmentName();
                LoadTemplates();
                VerifyUnclosedTask();
            }

        }

        private bool HasWaitingTasksToClose(Account account, Department department)
        {
            var tasks = _queryTask.WaitToCloseTasksOwnerInDepartment(account, department);
            return tasks.ToList().Count == 0;
        }
        private void VerifyUnclosedTask()
        {
            if (!HasWaitingTasksToClose(CurrentAccount, CurrentDepartment))
                View.ErrorMessage = TaskKernelResources.UnclosedTaskExist;
        }

        private void LoadTemplates()
        {
            var tmplates = _queryProposalForm.GetTemplatesByDepartment(CurrentDepartment);
            View.Templates = tmplates.ToView();
            var template = tmplates.FirstOrDefault();
            if (template != null)
                LoadTemplateHtml(template);
        }

        private void LoadTemplateHtml(Template template)
        {
            View.TemplateResourceName = template.ContentNameResource;
            View.TemplateHtml = (string)GetResource(template.ContentNameResource);
        }

        public virtual void OnViewLoaded()
        {
            using (var z = _uow.Create())
            {
                var template = _queryProposalForm.GetProposalForm(View.SelectedTemplate);
                LoadTemplateHtml(template);
            }
        }

        public virtual void OnSave()
        {

            if (ViewHasValidValues(View.UserValues))
            {
                object resourceName = GetResource(View.TemplateResourceName);
                var html = new StringReader((string)resourceName);
                string historyText = LiteralHelper.ParseHtml(html, View.UserValues);
                SendProposal(historyText);
            }
            else
                View.ErrorMessage = TaskKernelResources.RequiredField;

        }

        private void SendProposal(string historyText)
        {
            using (var z = _uow.Create())
            {
                _taskAction = new TaskServiceByRoleInDepartment(_taskAction, CurrentDepartment, CurrentAccount).GetAction();
                var template = _queryProposalForm.GetProposalForm(View.SelectedTemplate);
                var taskname = template.Name;
                if (!String.IsNullOrEmpty(taskname))
                {
                    if (HasWaitingTasksToClose(CurrentAccount, CurrentDepartment))
                    {
                        var task = new Task(CurrentAccount, CurrentDepartment, taskname);
                        _command.Save(task);
                        _taskAction = new TaskServiceByRoleInTask(_taskAction, task, CurrentAccount).GetAction();
                        ComplexSave(task, historyText);
                        _command.Save(task);
                        if (z.Commit())
                        {
                            _messageService.ChangeNotification(task, CurrentAccount, "Новая задача");
                            View.ErrorMessage = TaskKernelResources.ProposalFormValidMessage;
                        }
                    }
                    else
                        View.ErrorMessage = TaskKernelResources.UnclosedTaskExist;
                }
                else
                    View.ErrorMessage = TaskKernelResources.RequiredField;
            }
        }

        private void SaveDepartmentParticipants(Task task)
        {
            IEnumerable<Account> participants = CurrentDepartment.Participants;
            if (participants.Count() > 0)
                _taskAction.AddParticipant(task, participants.ToList(), CurrentAccount);
        }

        private void SaveManagersAccountAsParticipant(Task task)
        {
            IEnumerable<Account> managers = task.Owner.MasterAccounts;
            if (managers.Count() > 0)
                _taskAction.AddParticipant(task, managers, CurrentAccount);
        }

        private void SavePriority(Task task)
        {
            _taskAction.SetPriority(task, TaskPriority.Four);
        }

        private void ComplexSave(Task task, string historyText)
        {
            SaveHostName(task);
            SaveDepartmentParticipants(task);
            SavePriority(task);
            SaveManagersAccountAsParticipant(task);
            SaveHistoryEntries(task, historyText);
        }

        private void SaveHostName(Task task)
        {
            string historyText = View.IPAddress;
            if (!String.IsNullOrEmpty(historyText))
                _taskAction.AddComment(task, "IP: " + historyText, CurrentAccount);
        }

        private void SaveHistoryEntries(Task task, string historyText)
        {
            if (!String.IsNullOrEmpty(historyText))
                _taskAction.AddComment(task, historyText, CurrentAccount);
        }

        private static object GetResource(string resourceName)
        {
            Assembly cur = Assembly.GetExecutingAssembly();
            Type path = cur.GetTypes().SingleOrDefault(t => t.Name.Contains("ProposalResources"));
            var rm = new ResourceManager(path.FullName, cur);
            return rm.GetObject(resourceName);
        }

        private static bool ViewHasValidValues(ListDictionary keysValues)
        {
            if (keysValues.Count == 0) return false;
            foreach (DictionaryEntry entry in keysValues)
            {
                if (entry.Key.ToString().Contains("required"))
                {
                    if (String.IsNullOrEmpty((string)entry.Value))
                        return false;
                }
            }
            return true;
        }
    }
}